package it.alertManager.weather;

import it.alertManager.activity.R;
import it.alertManager.exceptions.AlertManagerException;
import it.alertManager.util.CommonData;

import java.io.IOException;
import java.io.StringReader;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.content.res.Resources;
import android.speech.tts.TextToSpeech;
import android.util.Log;

public class HTTPWeatherReader {
	
	private static final String LOG_CLASS_NAME = HTTPWeatherReader.class.getName();

	public WeatherData getURLOfWeatherForecast(String city, Locale loc) throws AlertManagerException
	{
		Log.d(LOG_CLASS_NAME,"Enter getURLOfWeatherForecast ");
		WeatherData weatherData = new WeatherData();
		
		String urlWeatherSite = null;
		if (loc.getLanguage().equals(Locale.ITALIAN.toString()))
			urlWeatherSite = CommonData.LIBERO_WEATHER_FORECAST_URL+URLEncoder.encode(city);
		else if (loc.getLanguage().equals(Locale.ENGLISH.toString()))
			urlWeatherSite = CommonData.GOOGLE_WEATHER_FORECAST_URL+URLEncoder.encode(city);
		
		String responseBody = CommonData.getResponse(urlWeatherSite);
		
		// I have found the search page
		ArrayList<String> resultFindAnchor = new ArrayList<String>();
		ArrayList<Integer> positionCityAnchor = new ArrayList<Integer>();
		if (responseBody.indexOf("Hai cercato:") != -1)
		{
			Pattern pattern = Pattern.compile("\\Q<a\\E.*\\Qhref=\"\\E.*\\Q.php?\\E.*\\Q</a>\\E");
		    Matcher matcher = pattern.matcher(responseBody);				
		    int cycle = -1;
		    while (matcher.find()) {
		        String anchorCity = responseBody.substring(matcher.start(), matcher.end()) + " ";
		        // Splitting
		        String[] anchorCityLst = anchorCity.split("\\s\\Q>\\E\\s");
		       
		        for (int i = 0; i < anchorCityLst.length; i++) 
		        {
		        	Log.d("PR", anchorCityLst[i]);
		        	cycle++;
			        if (anchorCityLst[i].trim().toLowerCase().contains(city+"</a>"))
			        {
			        	positionCityAnchor.add(new Integer(cycle));
			        }
			        resultFindAnchor.add(anchorCityLst[i].trim());						
				} 

		    }
		    CharSequence[] listOfCityCS = new CharSequence[positionCityAnchor.size()];
		    String[] listOfAnchorCityCS = new String[positionCityAnchor.size()];
		    cycle = 0;
			for (Integer integer : positionCityAnchor) {
				Log.d("PR", resultFindAnchor.get(integer.intValue() -1) + resultFindAnchor.get(integer.intValue()));
				String[] prov =  resultFindAnchor.get(integer.intValue()-1).split("\\Q>\\E|\\Q<\\E");
				String optionTemp = (city + " (" + prov[prov.length-2] + ")");
				listOfCityCS[cycle] = optionTemp.subSequence(0, optionTemp.length()); 
				String anchorCity = resultFindAnchor.get(integer.intValue());
				listOfAnchorCityCS[cycle] = anchorCity.substring(anchorCity.indexOf("href=\"")+6, anchorCity.indexOf("\">"));
				cycle++;
			} 
			weatherData.setListOfCityCS(listOfCityCS);
			weatherData.setListOfAnchorCityCS(listOfAnchorCityCS);			    
		}
		else
		{
			weatherData.setWeatherURL(urlWeatherSite);
		}

		Log.d(LOG_CLASS_NAME,"Exit getURLOfWeatherForecast ");
		return weatherData;
	}
	
	public void readWeatherForecastForIt(Resources res, TextToSpeech textToSpeech, String url, String responseBody) throws AlertManagerException
	{
		Log.d(LOG_CLASS_NAME,"Enter readWeatherForecastForIt ");
		

		if (responseBody == null)
			responseBody = CommonData.getResponse(url);

		String dateMessage = 
			responseBody.substring(responseBody.indexOf("Oggi"), 
					responseBody.indexOf('<', responseBody.indexOf("Oggi")));
		
		String minTemp = 
			(responseBody.substring(responseBody.indexOf("Min: ") + 4, 
					responseBody.indexOf('<', responseBody.indexOf("Min:")) -1)).trim();	

		String maxTemp = 
			(responseBody.substring(responseBody.indexOf("Max: ") + 4, 
					responseBody.indexOf('<', responseBody.indexOf("Max:")) -1)).trim();	
		
		// Handle of prevision Time
		ArrayList<String> previsionTime = new ArrayList<String>();
		String anchor = "/c/i/quadrato.jpg";

		int start = 0;
		int end = 0;
		int numOfPeriodOfDay = 0; 
		while ((start = responseBody.indexOf(anchor, start)) != -1)
		{
			end = responseBody.indexOf('<', start);
			String msg = (responseBody.substring(start + anchor.length() + 2, end)).trim();
			msg = (msg.substring(0, msg.indexOf(" "))).trim();
			start = end; 
			if (CommonData.periodOfDay.Notte.name().equals(msg) && numOfPeriodOfDay != 0)
				break;
			previsionTime.add(msg);
			numOfPeriodOfDay++;
		}
		
		// Handle of prevision weather
		ArrayList<String> previsionWeather = new ArrayList<String>();
		String anchorIcon ="/c/i/icone/prev/";			
		start = 0;
		end = 0;
		while ((start = responseBody.indexOf(anchorIcon, start)) != -1)
		{
			end = responseBody.indexOf("</td>", responseBody.indexOf("<br>", start));
			String msg = (responseBody.substring(responseBody.indexOf("<br>", start) + 4, end)).trim();
			start = end; 
			previsionWeather.add(msg);
		}
		
		textToSpeech.setLanguage(Locale.ITALIAN);
				
		textToSpeech.speak(res.getString(it.alertManager.activity.R.string.goodmorning_message) + ". " + dateMessage, TextToSpeech.QUEUE_ADD, null);
		for (int ij = 0; ij < numOfPeriodOfDay; ij++)
		{
			String previsionTimeStr = previsionTime.get(ij);
			boolean maleSentence = !(previsionTimeStr.endsWith("a") || previsionTimeStr.endsWith("e"));
			String sentencePrevisionTime =  (maleSentence ? res.getString(R.string.for_the_male) : 
															res.getString(R.string.for_the_female)) 
															+ " " + previsionTimeStr + " "
															+ (maleSentence ? res.getString(R.string.is_forecast_male) :
																res.getString(R.string.is_forecast_female));
			
			textToSpeech.speak(sentencePrevisionTime, TextToSpeech.QUEUE_ADD, null);
			textToSpeech.speak(previsionWeather.get(ij), TextToSpeech.QUEUE_ADD, null);
		}
		textToSpeech.speak(res.getString(R.string.minimum_temp_sent) + " " + minTemp + ((minTemp.equals("1") || minTemp.equals("-1")) ? " grado" : " gradi"), TextToSpeech.QUEUE_ADD, null);
		textToSpeech.speak(res.getString(R.string.maximum_temp_sent) + " " + maxTemp + ((maxTemp.equals("1") || maxTemp.equals("-1")) ? " grado" : " gradi"), TextToSpeech.QUEUE_ADD, null);

		Log.d(LOG_CLASS_NAME,"Exit readWeatherForecastForIt ");
	}
		
	public void readWeatherForecastForEN(Resources res, TextToSpeech textToSpeech, String url, String responseBody) throws AlertManagerException
	{
		String responseBodyGoogle = CommonData.getResponse(url);
		
		try {
			DocumentBuilder builderweatherURL = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document doc = builderweatherURL.parse(new InputSource(new StringReader(responseBodyGoogle)));
			
			
			/**
			 * Error on response
			 */
			NodeList errorList = doc.getElementsByTagName("problem_cause");
			if (errorList.getLength() > 0)
			{
				Node errorNode = errorList.item(0);
				String errorMessage = errorNode.getAttributes().getNamedItem("data").getNodeValue();
				throw new AlertManagerException("Error on retrieving city: " + errorMessage + "\n Try to be specific", null);
			}
			
			/**
			 * Current weather condition.
			 */
			NodeList conditionList = doc.getElementsByTagName("condition");
			Node currentConditionNode = conditionList.item(0);
			String currentCondition = currentConditionNode.getAttributes().getNamedItem("data").getNodeValue();
			
			/**
			 * Current temperature.
			 */
			NodeList tempList = doc.getElementsByTagName("temp_c");
			Node currentTempNode = tempList.item(0);
			String currentTemp = currentTempNode.getAttributes().getNamedItem("data").getNodeValue();		
			
			/**
			 * Current humidity.
			 */
			NodeList humidityList = doc.getElementsByTagName("humidity");
			Node currentHumidityNode = humidityList.item(0);
			String currentHumidity = currentHumidityNode.getAttributes().getNamedItem("data").getNodeValue();
			
			/**
			 * Current wind weather.
			 */
			NodeList windConditionList = doc.getElementsByTagName("wind_condition");
			Node currentWindConditionNode = windConditionList.item(0);
			String currentWindCondition = currentWindConditionNode.getAttributes().getNamedItem("data").getNodeValue();

			
			StringBuffer message = new StringBuffer();
			message.append(res.getString(R.string.goodmorning_message))
					.append(". ")
					.append("the weather forecast for today is ")
					.append(currentCondition)
					.append(". The temperature forecast for today is ")
					.append(currentTemp)
					.append(" ° Celsius. ")
					.append("The value of ")
					.append(currentHumidity)
					.append(". The value of ")
					.append(currentWindCondition);

			textToSpeech.setLanguage(Locale.ENGLISH);
			textToSpeech.setSpeechRate(CommonData.SPEACH_RATE);
						
			textToSpeech.speak(message.toString(), TextToSpeech.QUEUE_ADD, null);
			Log.d(LOG_CLASS_NAME, doc.getElementsByTagName("img").toString());		
		} catch (ParserConfigurationException e) {
			Log.e(LOG_CLASS_NAME, "Error in HTTPWeatherReader: " + e.getMessage());
			throw new AlertManagerException("Error in HTTPWeatherReader: " + e.getMessage(), e);
		} catch (FactoryConfigurationError e) {
			Log.e(LOG_CLASS_NAME, "Error in HTTPWeatherReader: " + e.getMessage());
			throw new AlertManagerException("Error in HTTPWeatherReader: " + e.getMessage(), e);
		} catch (SAXException e) {
			Log.e(LOG_CLASS_NAME, "Error in HTTPWeatherReader: " + e.getMessage());
			throw new AlertManagerException("Error in HTTPWeatherReader: " + e.getMessage(), e);
		} catch (IOException e) {
			Log.e(LOG_CLASS_NAME, "Error in HTTPWeatherReader: " + e.getMessage());
			throw new AlertManagerException("Error in HTTPWeatherReader: " + e.getMessage(), e);
		}		
	}	
}
